/**
 * WTF Engine
 *
 * License... etc.
 **
 * XML Wrapper Classes
 **
 * Author: Sean Micklethwaite
 **/

#include "xml.h"

using namespace WtfEngine;

#ifdef __XML_XERCES__

XmlFile::XmlFile(): GcObject(), XmlIterator(NULL), mpParser(NULL) {
	static bool bInitialized = false;

	if(!bInitialized) {
		XMLPlatformUtils::Initialize();
		bInitialized = true;
	};
};

String XmlIterator::GetXml() {
	assert(mpNode);
	return String(mpNode->getNodeValue());
};

String XmlIterator::GetText(){
	assert(mpNode);
	return String(mpNode->getTextContent());
};

String XmlIterator::GetName() {
	assert(mpNode);
	return String(mpNode->getNodeName());
};

String XmlIterator::GetAttribute(const String& sName) {
	assert(mpNode);
	
	DOMNode * pNode = mpNode->getAttributes()->getNamedItem(sName.str());
	
	if(pNode) {
		return String(pNode->getNodeValue());
	} else {
		return String();
	};
};


/**
 * Iterates to the next node in the document. Text and CDATA nodes
 * are skipped, use GetText to get their value. Returns false
 * if the end of the document has been reached.
 **/
bool XmlIterator::NextNode() {
	DOMNode * pNode;
	assert(mpNode);

	for(pNode = mpNode->getFirstChild();
		pNode != NULL; pNode = pNode->getNextSibling())
	{
		if(pNode->getNodeType() == DOMNode::ELEMENT_NODE) {
			break;
		};
	};

	if(pNode == NULL) {
		if(NextSibling())
			return true;
	};

	//
	// Iterate up the tree, to parent's siblings
	//

	if(mpNode != mpRoot) {
		while(pNode == NULL && mpNode != NULL) {
			mpNode = mpNode->getParentNode();
			if(mpNode == mpRoot) break;

			for(pNode = mpNode->getNextSibling();
				pNode != NULL; pNode = pNode->getNextSibling())
			{
				if(pNode->getNodeType() == DOMNode::ELEMENT_NODE) {
					break;
				};
			};
		};
	};

	mpNode = pNode;
	return (mpNode != NULL);
};

bool XmlIterator::NextSibling() {
	DOMNode * pNode;
	assert(mpNode);

	if(mpNode == mpRoot) {
		for(pNode = mpNode->getFirstChild();
			pNode != NULL; pNode = pNode->getNextSibling())
		{
			if(pNode->getNodeType() == DOMNode::ELEMENT_NODE) {
				break;
			};
		};
	} else for(pNode = mpNode->getNextSibling();
		pNode != NULL; pNode = pNode->getNextSibling())
	{
		if(pNode->getNodeType() == DOMNode::ELEMENT_NODE) {
			break;
		};
	};

	mpNode = pNode;
	return (mpNode != NULL);
};

void XmlFile::Load(const String& sFile)
{
	// Free existing file
	Unload();

	// Create DOM Parser
	mpParser = new XercesDOMParser();
	mpParser->setValidationScheme(XercesDOMParser::Val_Always);

	//ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
    //parser->setErrorHandler(errHandler);

	try {
		// Invoke the parser
		mpParser->parse(sFile.str());
		mpRoot = mpParser->getDocument()->getDocumentElement();
		Reset();

	} catch(const XMLException& e) {
		throw new std::runtime_error(String("XML Parse failed: ") + String(e.getMessage()));
	} catch (const DOMException& e) {
		throw new std::runtime_error(String("XML Parse failed: ") + String(e.getMessage()));
	};
};

#endif
